Package org.python.pydev.debug.console

Source Code of org.python.pydev.debug.console.ConsoleCompletionsPageParticipant$GetCompletionsInDebug

/**
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package org.python.pydev.debug.console;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.internal.ui.views.console.ProcessConsole;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.IConsolePageParticipant;
import org.eclipse.ui.console.TextConsoleViewer;
import org.eclipse.ui.internal.console.IOConsolePage;
import org.eclipse.ui.internal.console.IOConsolePartition;
import org.eclipse.ui.part.IPageBookViewPage;
import org.python.pydev.core.IInterpreterInfo;
import org.python.pydev.core.log.Log;
import org.python.pydev.debug.core.Constants;
import org.python.pydev.debug.model.AbstractDebugTarget;
import org.python.pydev.debug.model.PyDebugTarget;
import org.python.pydev.debug.model.PyStackFrame;
import org.python.pydev.debug.model.XMLUtils;
import org.python.pydev.debug.model.remote.AbstractDebuggerCommand;
import org.python.pydev.debug.model.remote.GetCompletionsCommand;
import org.python.pydev.debug.model.remote.ICommandResponseListener;
import org.python.pydev.debug.newconsole.PydevConsoleCommunication;
import org.python.pydev.debug.newconsole.PydevConsoleCompletionProcessor;
import org.python.pydev.debug.newconsole.PydevConsoleInterpreter;
import org.python.pydev.editor.codecompletion.PyCodeCompletionPreferencesPage;
import org.python.pydev.editor.codecompletion.PyContentAssistant;
import org.python.pydev.plugin.nature.PythonNature;

import com.aptana.interactive_console.console.IScriptConsoleCommunication;
import com.aptana.interactive_console.console.InterpreterResponse;
import com.aptana.shared_core.bindings.KeyBindingHelper;
import com.aptana.shared_core.callbacks.ICallback;
import com.aptana.shared_core.structure.Tuple;

/**
* Will provide code-completion in debug sessions.
*/
@SuppressWarnings("restriction")
public class ConsoleCompletionsPageParticipant implements IConsolePageParticipant {

    /**
     * @return the currently selected / suspended frame. If the console is passed, it will only return
     * a frame that matches the passed console. If no selected / suspended frame is found or the console
     * doesn't match, null is returned.
     */
    protected static PyStackFrame getCurrentSuspendedPyStackFrame(IConsole console) {
        IAdaptable context = DebugUITools.getDebugContext();

        if (context instanceof PyStackFrame) {
            PyStackFrame stackFrame = (PyStackFrame) context;
            if (!stackFrame.isTerminated() && stackFrame.isSuspended()) {
                if (console != null) {
                    //If a console is passed, we must check if it matches the console from the selected frame.
                    AbstractDebugTarget target = (AbstractDebugTarget) stackFrame.getAdapter(IDebugTarget.class);
                    if (DebugUITools.getConsole(target.getProcess()) != console) {
                        return null;
                    }
                }

                return stackFrame;
            }
        }
        return null;
    }

    /**
     * Class to get the completions in debug mode in a suspended frame.
     */
    public static class GetCompletionsInDebug implements IScriptConsoleCommunication, ICommandResponseListener {

        private static final ICompletionProposal[] EMPTY_COMPLETION_PROPOSALS = new ICompletionProposal[0];
        private ICompletionProposal[] receivedCompletions;
        private String actTok;
        private String text;
        private int offset;

        public String getDescription(String text) throws Exception {
            throw new RuntimeException("Not implemented");
        }

        /**
         * Gets the completions at the passed offset.
         */
        public ICompletionProposal[] getCompletions(String text, String actTok, int offset) throws Exception {
            this.text = text;
            this.actTok = actTok;
            this.offset = offset;
            PyStackFrame stackFrame = getCurrentSuspendedPyStackFrame(null);

            if (stackFrame != null) {
                AbstractDebugTarget target = (AbstractDebugTarget) stackFrame.getAdapter(IDebugTarget.class);
                if (target != null) {
                    GetCompletionsCommand cmd = new GetCompletionsCommand(target, actTok, stackFrame.getLocalsLocator()
                            .getPyDBLocation());
                    cmd.setCompletionListener(this);
                    target.postCommand(cmd);
                }
                return waitForCommand();
            }
            return EMPTY_COMPLETION_PROPOSALS;
        }

        /**
         * Keeps in a loop for 3 seconds or until the completions are found. If no completions are found in that time,
         * returns an empty array.
         */
        private ICompletionProposal[] waitForCommand() {
            int i = 300; //wait up to 3 seconds
            while (--i > 0 && receivedCompletions == null) {
                try {
                    Thread.sleep(10); //10 millis
                } catch (InterruptedException e) {
                    //ignore
                }
            }

            ICompletionProposal[] temp = receivedCompletions;
            receivedCompletions = null;
            if (temp == null) {
                Log.logInfo("Timeout for waiting for debug completions elapsed (3 seconds).");
                return EMPTY_COMPLETION_PROPOSALS;
            }
            return temp;
        }

        public void execInterpreter(String command, ICallback<Object, InterpreterResponse> onResponseReceived,
                ICallback<Object, Tuple<String, String>> onContentsReceived) {
            throw new RuntimeException("Not implemented");

        }

        public void close() throws Exception {
            throw new RuntimeException("Not implemented");
        }

        /**
         * Received when the completions command receives a response (ICommandResponseListener)
         * Converts the xml to completions.
         */
        public void commandComplete(AbstractDebuggerCommand cmd) {
            GetCompletionsCommand compCmd = (GetCompletionsCommand) cmd;
            try {
                String response = compCmd.getResponse();
                List<Object[]> fromServer = XMLUtils.convertXMLcompletionsFromConsole(response);
                List<ICompletionProposal> ret = new ArrayList<ICompletionProposal>();
                PydevConsoleCommunication.convertToICompletions(text, actTok, offset, fromServer, ret);
                receivedCompletions = ret.toArray(new ICompletionProposal[ret.size()]);
            } catch (CoreException e) {
                receivedCompletions = EMPTY_COMPLETION_PROPOSALS;
                Log.log(e);
            }

        }

        public void linkWithDebugSelection(boolean isLinkedWithDebug) {
            throw new RuntimeException("Not implemented");
        }

    }

    /**
     * The content assistant added to the console.
     */
    private PyContentAssistant contentAssist;

    public Object getAdapter(Class adapter) {

        return null;
    }

    /**
     * When a console page is initialized,
     */
    public void init(IPageBookViewPage page, final IConsole console) {
        if (!(console instanceof ProcessConsole)) {
            return;
        }
        ProcessConsole processConsole = (ProcessConsole) console;
        IProcess process = processConsole.getProcess();
        if (process == null) {
            return;
        }
        if (!PyCodeCompletionPreferencesPage.useCodeCompletion()
                || !PyCodeCompletionPreferencesPage.useCodeCompletionOnDebug()) {
            return;
        }
        String attribute = process.getAttribute(Constants.PYDEV_DEBUG_IPROCESS_ATTR);
        if (!Constants.PYDEV_DEBUG_IPROCESS_ATTR_TRUE.equals(attribute)) {
            //Only provide code-completion for pydev debug processes.
            return;
        }
        Control control = page.getControl();
        if (page instanceof IOConsolePage) {

            //Note that completions on "all letters and '_'" are already activated just by installing
            //the content assist, but the completions on the default keybinding is not, so, we have to
            //call it ourselves here.
            control.addKeyListener(new KeyListener() {
                public void keyPressed(KeyEvent e) {

                    if (KeyBindingHelper.matchesContentAssistKeybinding(e)) {
                        contentAssist.showPossibleCompletions();
                    }
                }

                public void keyReleased(KeyEvent e) {
                }
            });

            IOConsolePage consolePage = (IOConsolePage) page;
            TextConsoleViewer viewer = consolePage.getViewer();

            contentAssist = new PyContentAssistant() {
                public String showPossibleCompletions() {
                    //Only show completions if we're in a suspended console.
                    if (getCurrentSuspendedPyStackFrame(console) == null) {
                        return null;
                    }
                    return super.showPossibleCompletions();
                };
            };
            contentAssist.setInformationControlCreator(PyContentAssistant.createInformationControlCreator(viewer));
            ILaunch launch = process.getLaunch();
            IDebugTarget debugTarget = launch.getDebugTarget();
            IInterpreterInfo projectInterpreter = null;
            if (debugTarget instanceof PyDebugTarget) {
                PyDebugTarget pyDebugTarget = (PyDebugTarget) debugTarget;
                PythonNature nature = PythonNature.getPythonNature(pyDebugTarget.project);
                if (nature != null) {
                    try {
                        projectInterpreter = nature.getProjectInterpreter();
                    } catch (Throwable e1) {
                        Log.log(e1);
                    }
                }

            }
            contentAssist.install(new ScriptConsoleViewerWrapper(viewer, projectInterpreter));

            PydevConsoleInterpreter interpreter = new PydevConsoleInterpreter();
            interpreter.setConsoleCommunication(new GetCompletionsInDebug());

            IContentAssistProcessor processor = new PydevConsoleCompletionProcessor(interpreter, contentAssist);
            contentAssist.setContentAssistProcessor(processor, IOConsolePartition.INPUT_PARTITION_TYPE);
            contentAssist.setContentAssistProcessor(processor, IOConsolePartition.OUTPUT_PARTITION_TYPE);

            contentAssist.enableAutoActivation(true);
            contentAssist.enableAutoInsert(false);
            contentAssist.setAutoActivationDelay(PyCodeCompletionPreferencesPage.getAutocompleteDelay());
        }
    }

    public void dispose() {

    }

    public void activated() {

    }

    public void deactivated() {

    }

}
TOP

Related Classes of org.python.pydev.debug.console.ConsoleCompletionsPageParticipant$GetCompletionsInDebug

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.